package com.shopmall.config;

import com.shopmall.service.AdminService;
import com.shopmall.service.AdminUserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.StrictHttpFirewall;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

//spring security 的安全 service 是 AdminUserServiceImpl 接口实现类

/*

对于security的配置******************重要
　　新创建一个配置类继承 WebSecurityConfigurerAdapter

　　需要注意的几个方法（重写的方法）:

　　　　configure(HttpSecurity http)   ：     htpp请求安全处理

　　　　configure(AuthenticationManagerBuilder auth)    ：  自定义数据库权限认证

　　　　configure(WebSecurity web)    ：    WEB安全

*/


//Aop 拦截器
@Configuration
@EnableWebSecurity         // 开启注解
@EnableGlobalMethodSecurity(prePostEnabled = true)  // 开启注解
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    AdminService adminService;

    @Autowired
    AdminUserServiceImpl adminUserService;

    @Autowired
    MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Bean
    public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
        StrictHttpFirewall firewall = new StrictHttpFirewall();
        //此处可添加别的规则,目前只设置 允许双 //
        firewall.setAllowUrlEncodedDoubleSlash(true);
        return firewall;
    }

    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //授权的规则

        //放行静态资源，白名单
        String white_list[]={
                "/css/**","/fonts/**","/goods_pic/**","/head_pic/**","/img/**","/js/**","/map/**",
                "/scss/**"};

        http.csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/wechat/**","/","/login","/login_do","/exit","/error/**").permitAll()
                .antMatchers("/css/**","/fonts/**","/goods_pic/**","/head_pic/**","/img/**","/js/**","/map/**",
                        "/scss/**").permitAll()
//                .antMatchers("/admin/admin_sys","/admin/add_admin").hasAnyRole("ROOT")
//                .antMatchers("/user/**","/record/**","/admin/admin_mall").hasAnyRole("ROOT","SYS")
//                .antMatchers("/goods/**","/buy_list/**","/income/**","/self/**","/home","/exit").hasAnyRole("ROOT","SYS","MALL")
//                .anyRequest().authenticated()

                .and()
                .formLogin().loginPage("/login").successHandler(myAuthenticationSuccessHandler)
                .usernameParameter("username")
                .passwordParameter("password")
                .defaultSuccessUrl("/home")
                .failureForwardUrl("/login")
                .and()
                .logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/exit"))
                .and()
                .exceptionHandling().accessDeniedPage("/login")
                .and()
                .sessionManagement().invalidSessionUrl("/login");

    }

    /*
    报错信息：role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_root'

    报错信息：nested exception is java.lang.IllegalStateException: Can't configure antMatchers after anyRequest

    问题原因：
    使用SpringSecurity配置http顺序错误，不能在anyRequest()之后再配置permitAll()，
    anyRequest()必须是最后一个
     */

    //密码加密，最新的security必须使用密码加密
    @Bean
    public PasswordEncoder passwordEncoder(){
        //使用BCrypt加密
        return new BCryptPasswordEncoder();
    }


    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        /*
        //这是模拟用户，内存中的。正常应该从数据库中认证
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("hello").password(new BCryptPasswordEncoder().encode("123456")).roles("admin")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("root")).roles("admin");
*/

        auth.userDetailsService(adminUserService).passwordEncoder((NoOpPasswordEncoder.getInstance()));
                ; //user Details Service验证

    }

    //解除对静态资源的保护
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**","/fonts/**","/goods_pic/**","/head_pic/**","/img/**","/js/**","/map/**",
                "/scss/**","/templates/**");
    }

}


